package com.aloaproject.ciquta;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Utility class to browse properties, setter and getter of a generic object.
 * @author Daniele Demichelis
 */
final class ObjectReflectionWrapper {

    private Object object;

    ObjectReflectionWrapper(Object objectToInspect) {

        if(objectToInspect == null){
            throw new IllegalArgumentException("Parameter objectToInspect cannot be null.");
        }

        this.object = objectToInspect;
    }

    final Object getValueOfProperty(final String property) {

        if (property == null || property.trim().length()==0) {
            throw new IllegalArgumentException("Property has an illegal value.");
        }

        if(property.contains(".")){
            //recursion
            Object result = null;
            String simpleProperty = property.substring(0, property.indexOf("."));
            String restProperty = property.substring(property.indexOf(".")+1);
            try {
                ClassReflectionWrapper cr = new ClassReflectionWrapper(object.getClass());
                Method getterMethod = cr.getGetterMethod(simpleProperty);
                Object subObject;
                try {
                    subObject = getterMethod.invoke(this.object, new Object[]{});
                } catch (Exception ex) {
                    throw new RuntimeException(ex);
                }
                if(subObject == null){
                    result = null;
                }else{
                    ObjectReflectionWrapper subWrapper = new ObjectReflectionWrapper(subObject);
                    result = subWrapper.getValueOfProperty(restProperty);
                }
                return result;
            } catch (NoSuchMethodException ex) {
                result = false;
            }
            return result;
        }else{
            //base
            Object result = null;
            try {
                ClassReflectionWrapper cr = new ClassReflectionWrapper(object.getClass());
                if(cr.hasReadableProperty(property)){
                    Method getterMethod = cr.getGetterMethod(property);
                    result = getterMethod.invoke(this.object, new Object[]{});
                }
            } catch (NoSuchMethodException ex) {
                throw new RuntimeException("Object '" + object + "' instance of '" + object.getClass() + "' has no properties called '" + property + "'");
            } catch (Exception ex) {
                throw new RuntimeException("Error reading property '" + property + "' of object '" + object + "'");
            }
            return result;
        }
    }

    final boolean hasReadableProperty(final String property) {

        if(property == null || property.trim().length()==0){
            throw new IllegalArgumentException("Property has an illegal value.");
        }

        return new ClassReflectionWrapper(object.getClass())
                .hasReadableProperty(property);

    }

}
